from functools import update_wrapper

from django.template.response import TemplateResponse


class BaseAdmin:
    pass


class BaseModelAdmin:
    """Functionality common to both ModelAdmin and InlineAdmin."""

    def __init__(self, model, site):
        self.model = model
        self.model_meta = model._meta
        self.app_label = model._meta.app_label
        self.model_name = model._meta.model_name
        self.field_names = [field.name for field in self.model_meta.fields]
        self.site = site

    def get_field_names(self, request, extra_context=None):
        return self.field_names

    def get_values_list(self, request, extra_context=None):
        values_list = self.model.objects.values_list(
            *self.get_field_names(request, extra_context)
        )
        return values_list
    def each_context(self, request, extra_context=None):
        context = {
            "app_label": self.app_label,
            "model_name": self.model_name,
            "model_meta": self.model_meta,
            "field_names": self.get_field_names(request)
        }
        context.update(extra_context or {})

        return context

    autocomplete_fields = ()
    raw_id_fields = ()
    fields = None
    exclude = None
    fieldsets = None
    # form = forms.ModelForm
    filter_vertical = ()
    filter_horizontal = ()
    radio_fields = {}
    prepopulated_fields = {}
    formfield_overrides = {}
    readonly_fields = ()
    ordering = None
    sortable_by = None
    view_on_site = True
    show_full_result_count = True
    # checks_class = BaseModelAdminChecks


class ModelAdmin(BaseModelAdmin):
    """Encapsulate all admin options and functionality for a given model."""

    list_display = ("__str__",)
    list_display_links = ()
    list_filter = ()
    list_select_related = False
    list_per_page = 100
    list_max_show_all = 200
    list_editable = ()
    search_fields = ()
    search_help_text = None
    date_hierarchy = None
    save_as = False
    save_as_continue = True
    save_on_top = False
    # paginator = Paginator
    preserve_filters = True
    # show_facets = ShowFacets.ALLOW
    inlines = ()

    # Custom templates (designed to be over-ridden in subclasses)
    add_form_template = None
    change_form_template = None
    change_list_template = None
    delete_confirmation_template = None
    delete_selected_confirmation_template = None
    object_history_template = None
    popup_response_template = None

    # Actions
    actions = ()
    # action_form = helpers.ActionForm
    actions_on_top = True
    actions_on_bottom = False
    actions_selection_counter = True

    # checks_class = ModelAdminChecks
    @property
    def urls(self):
        # python3 -m pip install django-extensions
        # INSTALLED_APPS = [
        #     'apps.adminz',
        #     'apps.aliyun.apps.AliyunConfig',
        #     'apps.git.apps.GitConfig',
        #     'django.contrib.admin',
        #     'django.contrib.auth',
        #     'django.contrib.contenttypes',
        #     'django.contrib.sessions',
        #     'django.contrib.messages',
        #     'django.contrib.staticfiles',
        #     'django_extensions',
        # ]
        # python3 manage.py show_urls
        # return self.get_urls(), self.app_label, self.site.name # namespace会在site中注入
        return self.get_urls(), None, None

    def get_urls(self):
        from django.urls import path

        def wrap(view):
            def wrapper(*args, **kwargs):
                return self.site.adminz_view(view)(*args, **kwargs)

            wrapper.model_admin = self
            return update_wrapper(wrapper, view)

        info = self.model_meta.app_label, self.model_meta.model_name

        print(info)

        return [
            path("", wrap(self.change_list_view), name="%s_%s_changelist" % info)
        ]

    def change_list_view(self, request, extra_context=None):
        values_list = self.get_values_list(request, extra_context)

        context = self.site.each_context(request, self.each_context(request, extra_context))
        context.update({
            "values_list": values_list
        })

        return TemplateResponse(
            request,
            self.change_list_template
            or [
                "admin/%s/%s/change_form.html" % (self.app_label, self.model_name),
                "admin/%s/change_form.html" % self.app_label,
                "adminz/change_list.html",
            ],
            context
        )
